
#include "CwTrend.h"
#include "cw_trend_draw.h"
#include "trenddb.h"

#include <mem.h>
#include <photon/PhRender.h>


/* prototype declarations */
PtWidgetClass_t *CreateCwTrendClass (void);

/* widget class pointer - class structure, create function */
PtWidgetClassRef_t WCwTrend = { NULL, CreateCwTrendClass };
PtWidgetClassRef_t *CwTrend = &WCwTrend; 

//-----------------------------------------------------------------------------
// загрузка значений по умолчанию
//-----------------------------------------------------------------------------
static void cwtrend_dflts( PtWidget_t *widget )
{
	time_t t_tmp;
	char namebuf [255];
	
	CwTrendWidget_t		*trend 	= ( CwTrendWidget_t * ) widget;
	PtBasicWidget_t		*basic 	= ( PtBasicWidget_t * ) widget;

//	printf ("init start\n");
//	fflush (stdout);
	
	trend->n_series = 5;
	basic->fill_color		= Pg_TRANSPARENT;
	trend->grid_color 		= Pg_DCYAN;

	trend->color = calloc (trend->n_series, sizeof (*trend->color));
	trend->color [0] 		= Pg_BLACK;
	trend->color [1] 		= Pg_BLUE;
	trend->color [2] 		= Pg_DGREEN;
	trend->color [3] 		= Pg_RED;
	trend->color [4] 		= Pg_DCYAN;
	
	trend->labels = calloc (trend->n_series, sizeof (*trend->labels));	
	trend->labels [0] = strdup ("Iя\nкА");
	trend->labels [1] = strdup ("Iв\nА");
	trend->labels [2] = strdup ("Uя\nВ");
	trend->labels [3] = strdup ("n\nоб/мин");
	trend->labels [4] = strdup ("n(зад)\nоб/мин");

	trend->ax_fmt = calloc (trend->n_series, sizeof (*trend->ax_fmt));	
	trend->ax_fmt [0] = strdup ("%.1f");
	trend->ax_fmt [1] = strdup ("%.0f");
	trend->ax_fmt [2] = strdup ("%.0f");
	trend->ax_fmt [3] = strdup ("%.0f");
	trend->ax_fmt [4] = strdup ("%.0f");

	trend->n_vert = 10;
	trend->n_horz = 5;

	trend->top_mg = 10;
	trend->bot_mg = 35;
	trend->lft_mg = 50;
	trend->rgt_mg = 35;
	
	trend->mask = 0x1f;

	trend->max_y = calloc (trend->n_series, sizeof (*trend->max_y));	
	trend->max_y [0] = 4;
	trend->max_y [1] = 120;
	trend->max_y [2] = 900;
	trend->max_y [3] = 250;
	trend->max_y [4] = 250;
	
	trend->min_y = calloc (trend->n_series, sizeof (*trend->min_y));	
	trend->min_y [0] = 0;
	trend->min_y [1] = 0;
	trend->min_y [2] = 0;
	trend->min_y [3] = 0;
	trend->min_y [4] = 0;

	trend->scale = calloc (trend->n_series, sizeof (*trend->scale));	
	trend->scale [0] = 1;
	trend->scale [1] = 1;
	trend->scale [2] = 1;
	trend->scale [3] = 1;
	trend->scale [4] = 1;

	trend->time_win = 60 * 25;
	trend->time_end = time (&t_tmp);

	trend->data_buf = calloc (trend->n_series, sizeof (*trend->data_buf));	

	//sprintf (namebuf, "trend_%p", widget);
	//printf ("name = \"%s\"\n", namebuf);

	// remove it begin
	sprintf (namebuf, "trend_%p", widget);
	//printf ("name = \"%s\"\n", namebuf);

	if (!(trend->myself = IP_TaskCreateMe (IP_GetChannelID(), namebuf, NULL, NULL, 0))) {
	    fprintf (stderr, "Could not initialize Cascade IPC subsystem\n");
	}
	//trend->hmsg = IP_MsgCreate (NULL, IP_MsgDefaultSize(), 0);
	trend->hist = IP_NserveLookupName ("/trenddb");
	trend->historian = strdup ("/trenddb");

	trend->hist_name = calloc (trend->n_series, sizeof (*trend->hist_name));	
	trend->hist_name [0] = strdup ("Mentor_14_0502");
	trend->hist_name [1] = strdup ("Mentor_13_0502");
	trend->hist_name [2] = strdup ("Mentor_14_0304");
	trend->hist_name [3] = strdup ("Mentor_14_0304");
	trend->hist_name [4] = strdup ("Mentor_14_0117");
	// remove it end	

	trend->printing = 0;
//	printf ("init done\n");
//	fflush (stdout);	
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
static void cwtrend_destroy (PtWidget_t *widget)
{
	CwTrendWidget_t		*trend = ( CwTrendWidget_t * ) widget;
	int i;
	data_buf_t 		*data_buf;

	for (i= 0; i< trend->n_series; i++) {
		data_buf = &trend->data_buf [i];
		if (data_buf->values) {
			free (data_buf->values);
			data_buf->values = NULL;
		}
		data_buf->nvalues = 0;
		
		free (trend->labels [i]);
		free (trend->ax_fmt [i]);
		
		free (trend->hist_name [i]); // remove it
	}	
	
	free (trend->color);
	free (trend->max_y);
	free (trend->min_y);
	free (trend->scale);	
	
	free (trend->labels);
	free (trend->ax_fmt);	
	
	free (trend->hist_name);		// remove it
	IP_TaskDestroy (trend->myself);	// remove it
	IP_TaskDestroy (trend->hist);	// remove it
	free (trend->historian);		// remove it

}

//-----------------------------------------------------------------------------
// to do - remove it
//-----------------------------------------------------------------------------
static void cwtrend_load_data (PtWidget_t *widget, PtArg_t const *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t		*trend = ( CwTrendWidget_t * ) widget;
	//PtBasicWidget_t		*basic = ( PtBasicWidget_t * ) widget;
	
	int i, j;
	data_buf_t 		*data_buf;
	int				sts;
	
	double t_end = trend->time_end;
	double t_beg = t_end - trend->time_win;
	double t = t_end - t_beg;	
	
	for (i= 0; i< trend->n_series; i++) {
		data_buf = &trend->data_buf [i];
		if (data_buf->values) {
			free (data_buf->values);
			data_buf->values = NULL;
		}
		data_buf->nvalues = 0;
		sts = interpolate_data (trend->myself, trend->hist, trend->hist_name [i],
								t_beg, t_end, &data_buf->values, &data_buf->nvalues);

		if (sts == 0) {
			for (j= 0; j< data_buf->nvalues; j++) {
				if (data_buf->values [j].t > t_end) data_buf->values [j].t = t_end + t;
				if (data_buf->values [j].t < t_beg) data_buf->values [j].t = t_beg - t;
			}
		}	
	}

//	PtDamageWidget (widget);	
}

//-----------------------------------------------------------------------------
// remove it
//-----------------------------------------------------------------------------

static void set_hist_name (PtWidget_t *widget, PtArg_t const *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;
	int				i;
	int				loop = (arg->len < trend->n_series)? arg->len: trend->n_series;
	char**			str_array = (char**) arg->value;

	for (i=0; i< loop; i++) {
		free (trend->hist_name [i]);
		trend->hist_name [i] = strdup (str_array [i]);
	}
//	PtDamageWidget (widget);
}

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------

static void cwtrend_data_ptr (PtWidget_t *widget, PtArg_t const *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;
	int				nser = arg->len;
	data_buf_t*		data_buf = (data_buf_t*) arg->value;

	//printf ("nser = %d, n_series = %d\n", nser, trend->n_series);

	if ((nser >= trend->n_series) || (nser < 0)) {
		printf ("cw_trend_ptr: can't find nser = %d, trend->n_series = %d\n", nser, trend->n_series);
		return;			
	}
	
	if (trend->data_buf [nser].values) {
		free (trend->data_buf [nser].values);
		trend->data_buf [nser].values = NULL;
		trend->data_buf [nser].nvalues = 0;
		trend->data_buf [nser].last_update = 0;
	}

	trend->data_buf [nser].values = data_buf->values;
	trend->data_buf [nser].nvalues = data_buf->nvalues;
	trend->data_buf [nser].last_update = data_buf->last_update;
	
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------

static void cwtrend_draw_common (PtWidget_t *widget, PhTile_t *damage, PhRect_t *canvas)
{
	CwTrendWidget_t		*trend = ( CwTrendWidget_t * ) widget;
	PtBasicWidget_t		*basic = ( PtBasicWidget_t * ) widget;
	PhRect_t 			rect;
	PhPoint_t			p1, p2;

	int axis_margin = 0;
	int i;
	int y_min, y_max;
	
	double *cur_value = calloc (trend->n_series, sizeof (double));	
	double *ptr_value = calloc (trend->n_series, sizeof (double));
    
	time_t t_end;
	time_t t_beg;
	
	PgSetFillColor (basic->fill_color);
	PgSetStrokeColor (Pg_BLACK);
	PgDrawRect (canvas, Pg_DRAW_FILL_STROKE);
	PgFlush ();

	for (i = 0; i < trend->n_series; i++) {
		if ((trend->mask >> i)&1) {
			axis_margin += trend->lft_mg;
		}
	}

	rect = *canvas;
	rect.ul.x += axis_margin;
	rect.ul.y += trend->top_mg;
	rect.lr.x -= trend->rgt_mg;
	rect.lr.y -= trend->bot_mg;	

	trend->trend_rect = rect;
	PhDeTranslateRect (&trend->trend_rect, &canvas->ul);
		
	PgSetClipping (1, &rect);
	cw_trend_draw_grid (rect, trend->n_horz, trend->n_vert, trend->grid_color);	

	t_end = trend->time_end;
	t_beg = t_end - trend->time_win;

	if ((t_end > 0) && (t_beg > 0)) {
		for (i = 0; i < trend->n_series; i++) {
			if (!((trend->mask >> i)&1)) continue;	
			y_min = trend->min_y [i] * trend->scale [i];
			y_max = trend->max_y [i] * trend->scale [i];
			cw_trend_draw_yt_trend (trend, rect, i, t_beg, t_end, 0, 3, &cur_value [i], &ptr_value [i]);
			cur_value [i] /= trend->scale [i];
			ptr_value [i] /= trend->scale [i];
		}
		cw_trend_draw_cursor (trend, rect, ptr_value);
	} else {
		for (i = 0; i < trend->n_series; i++) {
			cur_value [i] = 0;
		}
	}

	PgSetClipping (0, NULL);

	p1.x = canvas->ul.x + axis_margin;
	p1.y = canvas->lr.y - trend->bot_mg;
	p2.x = canvas->lr.x - trend->rgt_mg;
	p2.y = p1.y;
	cw_trend_draw_time_axe (p1, p2, trend->n_horz, t_end, t_beg, trend->time_ptr);

	rect = *canvas;
	rect.lr.x = rect.ul.x + axis_margin;
	rect.ul.y += trend->top_mg;
	rect.lr.y -= trend->bot_mg;
	cw_trend_draw_axis (trend, rect, cur_value, trend->printing);

	free (cur_value);
	cur_value = NULL;
	free (ptr_value);
	ptr_value = NULL;

	PgFlush ();
	PgWaitHWIdle ();
	
}
//-----------------------------------------------------------------------------
// функция прорисовки всего widget'a
//-----------------------------------------------------------------------------
//#define USE_OSC // use offscreen context instead of memory context

static void cwtrend_draw (PtWidget_t *widget, PhTile_t *damage)
{
	CwTrendWidget_t		*trend = ( CwTrendWidget_t * ) widget;
	PtBasicWidget_t		*basic = ( PtBasicWidget_t * ) widget;
	PhRect_t canvas;
	
	//#ifdef USE_OSC
	PdOffscreenContext_t *osc = NULL;
	PhDrawContext_t *dc = NULL;
	//#else
	PmMemoryContext_t *mc = NULL;
	PhImage_t mc_image;
	PhDrawContext_t *odc = PhDCGetCurrent ();
	//#endif

	PtCalcCanvas (widget, &canvas);

	if (trend->selecting) {
		int dm;		
		PhRect_t r;
		PgSetStrokeColor (Pg_INVERT_COLOR);
		PgSetFillColor (Pg_INVERT_COLOR);
		dm = PgSetDrawMode (Pg_DRAWMODE_XOR);
		if (!trend->end_selecting)	{
			r = trend->prv_motion_rect;
			PhTranslateRect (&r, &canvas.ul);
			PgDrawRect (&r, Pg_DRAW_STROKE);			
		} else {
			trend->end_selecting = 0;
			trend->selecting = 0;
		}
		r = trend->motion_rect;
		PhTranslateRect (&r, &canvas.ul);		
		PgDrawRect (&r, Pg_DRAW_STROKE);
		PgSetDrawMode (dm);		
		return;
	}

	//#ifdef USE_OSC
	if (!trend->printing) {
		osc = PdCreateOffscreenContext (0, 
				canvas.lr.x - canvas.ul.x + 1,
				canvas.lr.y - canvas.ul.y + 1,
				0);//Pg_OSC_MEM_2D_WRITABLE);
		dc = PhDCSetCurrent(osc);
		PdSetOffscreenTranslation (osc, &canvas.ul);
		if (osc == NULL) printf ("cwtrend: error osc\n");
	}
	//#else	
	else {
		memset (&mc_image, 0, sizeof(PhImage_t));
		mc_image.type = Pg_IMAGE_DIRECT_888;
		mc_image.size.w = canvas.lr.x - canvas.ul.x + 1;
		mc_image.size.h = canvas.lr.y - canvas.ul.y + 1;
		mc = PmMemCreateMC (&mc_image, &mc_image.size, &canvas.ul);
		PmMemStart (mc);
	}
	//#endif
//	printf ("hello 1\n");

	if (!trend->printing) {
		basic->fill_color = PgRGB (217, 217, 217);	
	} else {
		basic->fill_color = Pg_WHITE;
	}
	cwtrend_draw_common (widget, damage, &canvas);

//	printf ("hello 2\n");

	//#ifdef USE_OSC
	if (!trend->printing) {
		PhDCSetCurrent (dc);	
		PgContextBlit (osc, &canvas, dc, &canvas);
		PgWaitHWIdle ();	
		PgFlush ();
		PhDCRelease (osc);
	}
	//#else
	else {
		PmMemFlush (mc, &mc_image);
		PmMemStop (mc);
		PhDCSetCurrent (odc);	
		PgDrawPhImage (&canvas.ul, &mc_image, 0);
		PgFlush ();
		PmMemReleaseMC (mc);
	}
	//#endif
}

//-----------------------------------------------------------------------------
// обработка событий (RAW)
//-----------------------------------------------------------------------------
static int raw_clbk (PtWidget_t *widget, void *apinfo, PtCallbackInfo_t *cbinfo)
{
	CwTrendWidget_t	*trend = (CwTrendWidget_t *) widget;

	PhPointerEvent_t *event_data;
	PhRect_t* r;
	
	static PhRect_t but_press_coord, but_release_coord;

	/* eliminate 'unreferenced' warnings */
	widget = widget, apinfo = apinfo, cbinfo = cbinfo;

	r = PhGetRects (cbinfo->event);

	// нажата нопка мыши
	switch (cbinfo->event->type) {
		case Ph_EV_BUT_PRESS: 
			event_data = (PhPointerEvent_t *) PhGetData (cbinfo->event);
//			printf ("event_data->click_count = %d\n", event_data->click_count);
			if (event_data->click_count == 2) {
				if (r->ul.x <= trend->trend_rect.lr.x) {
					trend->time_ptr = (trend->time_end) 									
									- (double)((r->ul.x - trend->trend_rect.ul.x) * trend->time_win) 
									/(double)(trend->trend_rect.lr.x - trend->trend_rect.ul.x);
					trend->selecting = 0;
					PtDamageWidget (widget);
//					printf ("trend->time_ptr = %f\n", trend->time_ptr);
				}
			} 
			else if (event_data->click_count == 1) {
				but_press_coord = *r;
				trend->selecting = 1;
				trend->prv_motion_rect.ul.x = trend->prv_motion_rect.ul.y = 0;
				trend->prv_motion_rect.lr.x = trend->prv_motion_rect.lr.y = 0;
				trend->motion_rect.ul.x = trend->motion_rect.ul.y = 0;
				trend->motion_rect.lr.x = trend->motion_rect.lr.y = 0;
			}
			break;
			
		case Ph_EV_BUT_RELEASE:
			if (cbinfo->event->subtype == Ph_EV_RELEASE_REAL) { 
				if (trend->selecting) {
					time_t t_beg, t_end;
					PhRect_t rect = trend->motion_rect;
					PhRectIntersect (&rect, &trend->trend_rect);
					if ((rect.ul.x - rect.lr.x) == 0 &&
						(rect.ul.y - rect.lr.y) == 0 ) {
						break;		
					}
					but_release_coord = *r;					
					t_end = (trend->time_end) 									
							- (double)((rect.ul.x - trend->trend_rect.ul.x) * trend->time_win) 
							/(double)(trend->trend_rect.lr.x - trend->trend_rect.ul.x);
					t_beg = (trend->time_end) 									
							- (double)((rect.lr.x - trend->trend_rect.ul.x) * trend->time_win) 
							/(double)(trend->trend_rect.lr.x - trend->trend_rect.ul.x);
					if (t_beg < t_end) {
						trend->end_selecting = 0;
						trend->selecting = 0;
						trend->time_end = t_end;
						trend->time_win = t_end - t_beg;
					} else {
						trend->end_selecting = 1;
					}					
					PtDamageWidget (widget);
				}
			}
			break;

		case Ph_EV_BOUNDARY:
			if (cbinfo->event->subtype == Ph_EV_PTR_LEAVE) {
				if (trend->selecting) {
					trend->end_selecting = 1;					
					PtDamageWidget (widget);
				}
			}
			break;
				
		case Ph_EV_PTR_MOTION_BUTTON:
			if (trend->selecting) {
				trend->prv_motion_rect = trend->motion_rect;
				trend->motion_rect.ul = but_press_coord.ul;
				trend->motion_rect.lr = r->lr;
				PtDamageWidget (widget);
			}
			break;
	}
	
	return (Pt_CONTINUE);
}
//-----------------------------------------------------------------------------

static void axis_set_labels (PtWidget_t *widget, PtArg_t const *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;
	int				i;
	int				loop = (arg->len < trend->n_series)? arg->len: trend->n_series;
	char**			str_array = (char**) arg->value;

	for (i=0; i< loop; i++) {
		free (trend->labels [i]);
		trend->labels [i] = strdup (str_array [i]);
	}
	//PtDamageWidget (widget);
}
//-----------------------------------------------------------------------------

static int axis_get_labels (PtWidget_t *widget, PtArg_t *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;

	if (arg->value)
		* (char ***) arg->value = trend->labels;
	return Pt_TRUE;
}
//-----------------------------------------------------------------------------

static void axis_set_miny (PtWidget_t *widget, PtArg_t const *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;
	int				i;
	int				loop = (arg->len < trend->n_series)? arg->len: trend->n_series;
	double*			array = (double*) arg->value;
		
	for (i=0; i< loop; i++ ) {
		trend->min_y [i] = array [i];
	}
	PtDamageWidget (widget);
}
//-----------------------------------------------------------------------------

static int axis_get_miny (PtWidget_t *widget, PtArg_t *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;

	if (arg->value)
		* (double **) arg->value = trend->min_y;
	return Pt_TRUE;
}
//-----------------------------------------------------------------------------

static void axis_set_maxy (PtWidget_t *widget, PtArg_t const *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;
	int				i;
	int				loop = (arg->len < trend->n_series)? arg->len: trend->n_series;
	double*			array = (double*) arg->value;

	for (i=0; i< loop; i++ ) {
		trend->max_y [i] = array [i];
	}
	PtDamageWidget (widget);
}
//-----------------------------------------------------------------------------

static int axis_get_maxy (PtWidget_t *widget, PtArg_t *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;

	if (arg->value) 
		* (double **) arg->value = trend->max_y;
	return Pt_TRUE;
}

//-----------------------------------------------------------------------------

static void set_n_series (PtWidget_t *widget, PtArg_t const *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;
	int				i;
	int				old_n_series = trend->n_series;

	trend->n_series = (int) arg->value;
	if (trend->n_series > 16) trend->n_series = 16;

	
	trend->color = realloc (trend->color, trend->n_series * sizeof (*trend->color));
	trend->labels = realloc (trend->labels, trend->n_series * sizeof (*trend->labels));	
	trend->ax_fmt = realloc (trend->ax_fmt, trend->n_series * sizeof (*trend->ax_fmt));	
	trend->max_y = realloc (trend->max_y, trend->n_series * sizeof (*trend->max_y));	
	trend->min_y = realloc (trend->min_y, trend->n_series * sizeof (*trend->min_y));	
	trend->scale = realloc (trend->scale, trend->n_series * sizeof (*trend->scale));	
	trend->data_buf = realloc (trend->data_buf, trend->n_series * sizeof (*trend->data_buf));	
	trend->mask = 0xff;

	for (i=0; i< trend->n_series; i++) {
		trend->scale [i] = 1;
	}
		
	if (trend->n_series > old_n_series) {
		for (i= old_n_series; i< trend->n_series; i++) {
			trend->color [i] = Pg_BLACK;
			memset (&trend->data_buf [i], 0, sizeof (*trend->data_buf));			
		}
	}	
	
	PtDamageWidget (widget);
}
//-----------------------------------------------------------------------------

static int get_n_series (PtWidget_t *widget, PtArg_t *arg, PtResourceRec_t const *res_rec)
{
	CwTrendWidget_t *trend = (CwTrendWidget_t *) widget;

	if (arg->value) 
		* (int **) arg->value = &trend->n_series;
	return Pt_TRUE;
}
//-----------------------------------------------------------------------------

static void cwtrend_calc_opaque (PtWidget_t *widget)
{
//	PtBasicWidget_t *basic = (PtBasicWidget_t *) widget;

	// must have RECTANGULAR class flag set
	if (widget->class_rec->flags & Pt_RECTANGULAR) {
		widget->flags |= Pt_OPAQUE;
	}
}

//-----------------------------------------------------------------------------
// создание класса
//-----------------------------------------------------------------------------
PtWidgetClass_t *CreateCwTrendClass( void )
{
	static const PtRawCallback_t callback = {
		Ph_EV_BUT_PRESS | Ph_EV_BUT_RELEASE | Ph_EV_PTR_MOTION_BUTTON | Ph_EV_BOUNDARY,	
		raw_clbk,	NULL
	};
		// define our resources
	static PtResourceRec_t resources[] = {
		{TREND_ARG_GRID_COLOR, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, grid_color)},

 		{TREND_ARG_AXIS_LABELS, axis_set_labels, axis_get_labels, 0, 0},
 		{TREND_ARG_AXIS_MINY, axis_set_miny, axis_get_miny, 0, 0},
 		{TREND_ARG_AXIS_MAXY, axis_set_maxy, axis_get_maxy, 0, 0},
		{TREND_ARG_AXIS_MASK, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, mask)},
 		{TREND_ARG_N_AXIS, set_n_series, get_n_series, 0, 0},

		{TREND_ARG_TOP_MG, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, top_mg)},
		{TREND_ARG_BOT_MG, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, bot_mg)},
		{TREND_ARG_LFT_MG, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, lft_mg)},
		{TREND_ARG_RGT_MG, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, rgt_mg)},
			
		{TREND_ARG_TIME_END, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, time_end)},
		{TREND_ARG_TIME_WIN, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, time_win)},
		{TREND_ARG_TIME_PTR, Pt_CHANGE_REDRAW, 0, 
			Pt_ARG_IS_STRUCT (CwTrendWidget_t, time_ptr)},
			
		{TREND_ARG_PRINTING, Pt_CHANGE_INVISIBLE, 0, 
			Pt_ARG_IS_NUMBER (CwTrendWidget_t, printing)},

		{TREND_ARG_LOAD_DATA, cwtrend_load_data, NULL, 0, 0}, 	// remove it					
 		{TREND_ARG_HIST_NAME, set_hist_name, NULL, 0},			// remove it

		{TREND_ARG_DATA_PTR, cwtrend_data_ptr, NULL, 0, 0},								
	};

	// set up our class member values
	static PtArg_t args[] = {
		{ Pt_SET_VERSION, 110},
		{ Pt_SET_STATE_LEN, sizeof (CwTrendWidget_t) },
		{ Pt_SET_DFLTS_F, (long)cwtrend_dflts },
		{ Pt_SET_DESTROY_F, (long)cwtrend_destroy },
		{ Pt_SET_DRAW_F, (long)cwtrend_draw },
		{ Pt_SET_CALC_OPAQUE_F, (long)cwtrend_calc_opaque },
		{ Pt_SET_RAW_CALLBACKS, (long)&callback, 1 },
		{ Pt_SET_NUM_RESOURCES, sizeof (resources)/sizeof (resources[0])},
		{ Pt_SET_RESOURCES, (long)resources, sizeof (resources)/sizeof (resources[0])},
	};

	// create the widget class
	return (CwTrend->wclass = PtCreateWidgetClass (
		PtBasic, 0, sizeof (args)/sizeof (args[0]), args));
}